﻿using System;
using System.Web;
using System.Web.UI;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace MvcSupplantCaching.UnitTests
{
    [TestClass]
    public class CacheHeadersHelperTest : BaseTest
    {
        private Mock<HttpCachePolicyBase> _cache;

        [TestInitialize]
        public void TestInit()
        {
            var timestamp = DateTime.UtcNow;
            _cache = new Mock<HttpCachePolicyBase>();
            _cache.Setup(c => c.SetCacheability(It.Is<HttpCacheability>(p => p == HttpCacheability.Public))).Verifiable();
            _cache.Setup(c => c.SetExpires(It.Is<DateTime>(p => p == timestamp.AddSeconds(20)))).Verifiable();
            _cache.Setup(c => c.SetMaxAge(It.Is<TimeSpan>(p => p == TimeSpan.FromSeconds(20)))).Verifiable();
            _cache.Setup(c => c.SetValidUntilExpires(It.Is<bool>(p => p))).Verifiable();
            _cache.Setup(c => c.SetLastModified(It.Is<DateTime>(p => p == timestamp))).Verifiable();
            _cache.Setup(c => c.SetSlidingExpiration(It.Is<bool>(p => p == false))).Verifiable();
            HttpResponse.Setup(r => r.Cache).Returns(() => _cache.Object);
        }

        private void TestLocation(CacheSettings settings, HttpCacheability cacheability)
        {
            _cache.Setup(r => r.SetCacheability(It.IsAny<HttpCacheability>())).Callback<HttpCacheability>(x => Assert.AreEqual(cacheability, x));

            var helper = new CacheHeadersHelper();
            helper.SetCacheHeaders(HttpResponse.Object, settings);
        }

        [TestMethod]
        public void TestLocationAny()
        {
            CacheSettings settings = new CacheSettings
            {
                Location = OutputCacheLocation.Any
            };

            TestLocation(settings, HttpCacheability.Public);
        }

        [TestMethod]
        public void TestLocationDownstream()
        {
            CacheSettings settings = new CacheSettings
            {
                Location = OutputCacheLocation.Downstream
            };

            TestLocation(settings, HttpCacheability.Public);
        }

        [TestMethod]
        public void TestLocationClient()
        {
            CacheSettings settings = new CacheSettings
            {
                Location = OutputCacheLocation.Client
            };

            TestLocation(settings, HttpCacheability.Private);
        }

        [TestMethod]
        public void TestLocationServerAndClient()
        {
            CacheSettings settings = new CacheSettings
            {
                Location = OutputCacheLocation.ServerAndClient
            };

            TestLocation(settings, HttpCacheability.Private);
        }

        [TestMethod]
        public void TestNoStore()
        {
            CacheSettings settings = new CacheSettings
            {
                Location = OutputCacheLocation.Any
            };

            // If the callback gets hit, then settings.NoStore should be true.
            _cache.Setup(r => r.SetNoStore()).Callback(() => Assert.IsTrue(settings.NoStore));

            var helper = new CacheHeadersHelper();
            helper.SetCacheHeaders(HttpResponse.Object, settings);
        }
    }
}
